package com.yuyou.fn.educational.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.wens.mybatisplus.examples.Example;
import com.github.wens.mybatisplus.plugins.Page;
import com.github.wens.mybatisplus.toolkit.StringUtil;
import com.google.common.collect.Lists;
import com.yuyou.fn.common.constant.ClassLevelEnum;
import com.yuyou.fn.common.exception.BusException;
import com.yuyou.fn.common.service.IEmailService;
import com.yuyou.fn.common.service.ISiteConfigService;
import com.yuyou.fn.common.service.ISmsService;
import com.yuyou.fn.common.util.*;
import com.yuyou.fn.educational.entity.*;
import com.yuyou.fn.educational.service.*;
import com.yuyou.fn.educational.vo.FullClassSaveVo;
import com.yuyou.fn.educational.vo.ApplyClassDetailVo;
import com.yuyou.fn.educational.vo.ApplyClassQueryVo;
import com.yuyou.fn.educational.vo.ApplyClassSaveOrUpdateVo;
import com.yuyou.fn.platform.entity.AreaTeam;
import com.yuyou.fn.platform.entity.BusTeam;
import com.yuyou.fn.platform.entity.SysUser;
import com.yuyou.fn.platform.permission.DataPermission;
import com.yuyou.fn.platform.service.IAreaTeamService;
import com.yuyou.fn.platform.service.IBusTeamService;
import com.yuyou.fn.platform.service.ISysUserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.yuyou.fn.educational.mapper.ApplyClassMapper;
import com.github.wens.framework.service.impl.SuperServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.awt.geom.Area;
import java.util.*;

/**
 *
 * ApplyClass 表数据服务层接口实现类
 *
 */
@Service
public class ApplyClassServiceImpl extends SuperServiceImpl<ApplyClassMapper, ApplyClass,Long> implements IApplyClassService {



    @Resource
    private ITeacherService teacherService;

    @Resource
    private IAreaTeamService areaTeamService;

    @Resource
    private IBusTeamService busTeamService;

    @Resource
    private IBaseSubjectService baseSubjectService;

    @Resource
    private IBaseGradeService baseGradeService;

    @Resource
    private ISmsService smsService;

    @Resource
    private IPeriodService periodService;

    @Resource
    private ICourseClassService courseClassService;

    @Resource
    private ISysUserService sysUserService;


    @Resource
    private ISiteConfigService siteConfigService;

    @Resource
    private IEmailService emailService;

    @Value("${dev.env}")
    private boolean dev;

    @Override
    public void saveOrUpdateApplyClass(ApplyClassSaveOrUpdateVo applyClassSaveOrUpdateVo) {
        if (applyClassSaveOrUpdateVo.getApplyClassId()!=null){
            ApplyClass check=this.findById(applyClassSaveOrUpdateVo.getApplyClassId());
            if (check.getAuditStatus()!=0){
                throw new BusException("已经审核不可修改");
            }
        }

        BusTeam busTeam=busTeamService.findById(applyClassSaveOrUpdateVo.getBusTeamId());
        ApplyClass applyClass =new ApplyClass();
        Principals.Principal principal=Principals.get();
        BeanUtils.copyProperties(applyClass, applyClassSaveOrUpdateVo);
        applyClass.setUpdateTime(TimeUtils.now());

        applyClass.setAuditStatus(0);
        applyClass.setGenerateClassStatus(0);
        applyClass.setProposerId(principal.id);
        applyClass.setProposerName(principal.name);

        if (applyClass.getApplyClassId()==null){
            applyClass.setCreateTime(TimeUtils.now());
            this.insert(applyClass);
        }else {
            this.updateSelectiveById(applyClass);
        }

        List<String> emails=this.findAuditEmailsByAreaTeamId(applyClassSaveOrUpdateVo.getAreaTeamId(),"notify_audit_email");
        String message="您好！"+busTeam.getName()+"提交了新班级申请："+ applyClassSaveOrUpdateVo.getClassName()+"，请及时审核，谢谢！";
        String subject="新增班级申请";
        if (!dev){
            for (String email:emails){
                this.sendEmail(email,subject,message);
            }
        }
    }

    @Override
    public Page<ApplyClassDetailVo> findApplyClassDetailPage(DataPermission dataPermission,ApplyClassQueryVo applyClassQueryVo, int pageNo, int pageSize) {
        Long areaTeamId= applyClassQueryVo.getAreaTeamId();

        Example<ApplyClass> example= ApplyClass.createExample();
        Example.Criteria criteria=example.createCriteria();
        CriteriaUtils.fillCondition(criteria, applyClassQueryVo);
        CriteriaUtils.fillConditionForBusPermission(criteria,dataPermission.getBusTeamIds());
        example.orderBy("createTime").desc();
        Page<ApplyClass> page = this.findPageByExample(example,pageNo,pageSize);
        Page<ApplyClassDetailVo> applyClassDetailVoPage=Utils.newPage(page);

        List<ApplyClass> applyClassList =page.getRecords();
        List<Long> teacherIds = Utils.unique(BeanUtils.toList(applyClassList, "teacherId"));
        List<Teacher> teacherList=teacherService.findByIds(teacherIds,"teacherName","teacherId");
        Map<Long, Teacher> teacherMap = BeanUtils.toMap(teacherList, "teacherId");
        Map<Long,BusTeam> busTeamMap=busTeamService.findBusTeamMapByAreaTeamId(areaTeamId);
        AreaTeam areaTeam=areaTeamService.findById(areaTeamId);
        Map<Long,BaseGrade> baseGradeMap=baseGradeService.findGradeMap();
        Map<Long,BaseSubject> baseSubjectMap=baseSubjectService.findSubjectMap();
        Map<Long,Period> periodMap=periodService.findPeriodMapByAreaTeamId(areaTeamId);
        List<ApplyClassDetailVo> list = Lists.transform(applyClassList, (item) -> {
            ApplyClassDetailVo applyClassDetailVo =new ApplyClassDetailVo();
            BeanUtils.copyProperties(applyClassDetailVo,item);
            applyClassDetailVo.setAreaTeamName(areaTeam.getName());
            applyClassDetailVo.setBusTeamName(busTeamMap.get(item.getBusTeamId()).getName());
            if (item.getTeacherId()!=null){
                applyClassDetailVo.setTeacherName(teacherMap.get(item.getTeacherId()).getTeacherName());
            }
            applyClassDetailVo.setGradeName(baseGradeMap.get(item.getGradeId()).getGradeName());
            applyClassDetailVo.setSubjectName(baseSubjectMap.get(item.getSubjectId()).getSubjectName());
            applyClassDetailVo.setPeriodName(periodMap.get(item.getPeriodId()).getPeriodName());
            return applyClassDetailVo;
        });
        applyClassDetailVoPage.setRecords(list);
        return applyClassDetailVoPage;
    }

    @Override
    public ApplyClassDetailVo findApplyClassDetail(long applyClassId) {
        ApplyClass applyClass=this.findById(applyClassId);
        AreaTeam areaTeam=areaTeamService.findById(applyClass.getAreaTeamId());
        BusTeam busTeam=busTeamService.findById(applyClass.getBusTeamId());
        Period period=periodService.findById(applyClass.getPeriodId());
        Teacher teacher=teacherService.findById(applyClass.getTeacherId());
        BaseGrade baseGrade=baseGradeService.findById(applyClass.getGradeId());
        BaseSubject baseSubject=baseSubjectService.findById(applyClass.getSubjectId());
        ApplyClassDetailVo applyClassDetailVo=new ApplyClassDetailVo();
        BeanUtils.copyProperties(applyClassDetailVo,applyClass);
        applyClassDetailVo.setAreaTeamName(areaTeam.getName());
        applyClassDetailVo.setBusTeamName(busTeam.getName());
        applyClassDetailVo.setPeriodName(period.getPeriodName());
        applyClassDetailVo.setTeacherName(teacher==null?"":teacher.getTeacherName());
        applyClassDetailVo.setGradeName(baseGrade.getGradeName());
        applyClassDetailVo.setSubjectName(baseSubject.getSubjectName());

        return applyClassDetailVo;
    }

    @Override
    public SXSSFWorkbook exportApplyClassDetail(DataPermission dataPermission, ApplyClassQueryVo queryVo) {
        Page<ApplyClassDetailVo> applyClassDetailPage = this.findApplyClassDetailPage(dataPermission, queryVo, 1, 20000);
        return applyClassDetail2excel(applyClassDetailPage.getRecords());
    }

    public static SXSSFWorkbook applyClassDetail2excel(List<ApplyClassDetailVo> applyClassDetailVoList) {

        SXSSFWorkbook excel = new SXSSFWorkbook();
        SXSSFSheet sheet = excel.createSheet("班级申请列表");
        SXSSFRow firstRow = sheet.createRow(0);
        String[] titles = new String[]{ "区域","期数","业务组","年级", "科目","层级",  "班级名称", "开课日期","开课时间","主讲老师","增开原因", "申请人", "申请时间","审核状态", "审核理由"};
        for (int i = 0; i < titles.length; i++) {
            firstRow.createCell(i).setCellValue(titles[i]);
        }
        int rowNum = 1;

        if (applyClassDetailVoList!=null){
            for (ApplyClassDetailVo applyClassDetailVo : applyClassDetailVoList) {
                int cellNum = 0;

                SXSSFRow row = sheet.createRow(rowNum++);

                SXSSFCell cell = row.createCell(cellNum++);
                cell.setCellValue(StringUtils.defaultString(applyClassDetailVo.getAreaTeamName()));

                cell = row.createCell(cellNum++);
                cell.setCellValue(StringUtils.defaultString(applyClassDetailVo.getPeriodName()));

                cell = row.createCell(cellNum++);
                cell.setCellValue(StringUtils.defaultString(applyClassDetailVo.getBusTeamName()));

                cell = row.createCell(cellNum++);
                cell.setCellValue(StringUtils.defaultString(applyClassDetailVo.getGradeName()));

                cell = row.createCell(cellNum++);
                cell.setCellValue(StringUtils.defaultString(applyClassDetailVo.getSubjectName()));

                cell = row.createCell(cellNum++);
                cell.setCellValue(EnumUtils.getName(ClassLevelEnum.values() ,applyClassDetailVo.getLevel()));

                cell = row.createCell(cellNum++);
                cell.setCellValue(StringUtils.defaultString(applyClassDetailVo.getClassName()));

                cell = row.createCell(cellNum++);
                cell.setCellValue(applyClassDetailVo.getStartCourseTime()==null?"":Utils.formatDate(applyClassDetailVo.getStartCourseTime(),"yyyy-MM-dd"));

                cell = row.createCell(cellNum++);
                cell.setCellValue(StringUtils.defaultString(applyClassDetailVo.getStudyingTime()));



                cell = row.createCell(cellNum++);
                cell.setCellValue(StringUtils.defaultString(applyClassDetailVo.getTeacherName()));

                cell = row.createCell(cellNum++);
                cell.setCellValue(StringUtils.defaultString(applyClassDetailVo.getApplyReason()));

                cell = row.createCell(cellNum++);
                cell.setCellValue(StringUtils.defaultString(applyClassDetailVo.getProposerName()));

                cell = row.createCell(cellNum++);
                cell.setCellValue(applyClassDetailVo.getCreateTime()==null?"":Utils.formatDate(applyClassDetailVo.getCreateTime(),"yyyy-MM-dd HH:mm:ss"));


                cell = row.createCell(cellNum++);
                cell.setCellValue(StringUtils.defaultString(ApplyClass.auditStatusMap.get(applyClassDetailVo.getAuditStatus())));



                cell = row.createCell(cellNum++);
                cell.setCellValue(StringUtils.defaultString(applyClassDetailVo.getAuditReason()));


            }
        }


        return excel;
    }



    @Override
    public void auditFailureApplyClass(long applyClassId,String auditReason) {
        ApplyClass applyClass =this.findById(applyClassId);
        if (applyClass.getAuditStatus()!=0){
            throw new BusException("该数据已经审核过");
        }
        if ( this.changeApplyClassStatus(applyClassId,auditReason,2)){
            SysUser sysUser = sysUserService.findById(applyClass.getProposerId());
            String phoneNo=sysUser.getPhoneNo();
            String message="您好！您所申请新增班级"+ applyClass.getClassName()+"，尚未通过审核，请登录系统查看明细，谢谢！";
            this.sendMessage(phoneNo,message);
        }

    }


    @Override
    public void auditSuccessApplyClass(long applyClassId, String auditReason) {
        ApplyClass applyClass =this.findById(applyClassId);
        BusTeam busTeam=busTeamService.findById(applyClass.getBusTeamId());
        if (applyClass.getAuditStatus()!=0){
            throw new BusException("该数据已经审核过");
        }
        if ( this.changeApplyClassStatus(applyClassId,auditReason,1)){
            List<String> emails=this.findAuditEmailsByAreaTeamId(applyClass.getAreaTeamId(),"notify_create_email");
            String message="您好！"+busTeam.getName()+"提交了新班级申请："+ applyClass.getClassName()+"，请及时审核，谢谢！";
            String subject="新增班级申请";
            if (!dev){
                for (String email:emails){
                    this.sendEmail(email,subject,message);
                }
            }
        }
    }

    @Override
    public boolean changeApplyClassStatus(long applyClassId, String auditReason,int auditStatus) {
        Principals.Principal principal=Principals.get();
        ApplyClass update=new ApplyClass();
        update.setAuditPersonId(principal.id);
        update.setAuditPersonName(principal.name);
        update.setAuditStatus(auditStatus);
        update.setAuditReason(auditReason);
        update.setUpdateTime(TimeUtils.now());
        update.setApplyClassId(applyClassId);
        return this.updateSelectiveById(update);
    }

    @Override
    @Transactional
    public void createClassByApply(long applyClassId, FullClassSaveVo fullClassSaveVo) {
        ApplyClass applyClass =this.findById(applyClassId);
        if (applyClass.getAuditStatus()!=1){
            throw new BusException("审核通过才能生成数据");
        }

        if (applyClass.getGenerateClassStatus()==1){
            throw new BusException("该数据已生成过班级");
        }
        CourseClass courseClass = courseClassService.saveClassByFullMessage(fullClassSaveVo);
        this.fillClassId(applyClassId,courseClass.getClassId());
        String message = "您好！您所申请新增班级" + fullClassSaveVo.getClassName() + "，已经通过审核，请登录系统查看明细，谢谢！";
        SysUser sysUser = sysUserService.findById(applyClass.getProposerId());
        String phoneNo = sysUser.getPhoneNo();
        this.sendMessage(phoneNo, message);


    }

    @Override
    public boolean fillClassId(long applyClassId,long classId) {
        ApplyClass update=new ApplyClass();
        update.setUpdateTime(TimeUtils.now());
        update.setGenerateClassId(classId);
        update.setGenerateClassStatus(1);
        update.setApplyClassId(applyClassId);
        return this.updateSelectiveById(update);
    }

    private void sendEmail(String email,String subject ,String content){
        if (StringUtils.isNotEmpty(email) && StringUtils.isNotEmpty(subject) && StringUtil.isNotEmpty(content)){
            Threads.dispatch(new Runnable() {
                @Override
                public void run() {
                    try {
                        emailService.sendEmail(email,subject,content,null,null);
                    } catch (Exception e) {

                    }
                }
            });
        }
    }

    private void sendMessage(String phoneNo, String message){
        if (StringUtils.isNotEmpty(phoneNo) && StringUtils.isNotEmpty(message)){
            Threads.dispatch(new Runnable() {
                @Override
                public void run() {
                    try {
                        smsService.send(Arrays.asList(phoneNo) ,message);
                    } catch (Exception e) {

                    }
                }
            });
        }
    }



    private List<String> findAuditEmailsByAreaTeamId(Long areaTeamId,String configName){
        String  s=siteConfigService.findConfigValue(configName);
        JSONObject jsonObject=JSONObject.parseObject(s);
        JSONArray jsonArray=jsonObject.getJSONArray(areaTeamId.toString());
        if (jsonArray!=null){
            return jsonArray.toJavaList(String.class);
        }
        return Collections.EMPTY_LIST;
    }
}